﻿Public Class MessageService
#Region "Singleton"
    Private Shared mInstance As MessageService
    Public Shared ReadOnly Property Instance As MessageService
        Get
            If mInstance Is Nothing Then
                mInstance = New MessageService
            End If
            Return mInstance
        End Get
    End Property
#End Region

    Private mMessages As Dictionary(Of Type, List(Of IMessageListener))

    Private Sub New()
        mMessages = New Dictionary(Of Type, List(Of IMessageListener))
    End Sub

    ''' <summary>
    ''' Registers an IMessageListener to receive a specific type of message
    ''' </summary>
    ''' <typeparam name="MessageType"></typeparam>
    ''' <param name="listener"></param>
    ''' <remarks></remarks>
    Public Sub RegisterListener(Of MessageType)(listener As IMessageListener)
        Dim listeners As List(Of IMessageListener) = Nothing
        If Not mMessages.TryGetValue(GetType(MessageType), listeners) Then
            listeners = New List(Of IMessageListener)
            mMessages.Add(GetType(MessageType), listeners)
        End If
        listeners.Add(listener)
    End Sub
    Public Sub RegisterListener(messageType As Type, listener As IMessageListener)
        Dim listeners As List(Of IMessageListener) = Nothing
        If Not mMessages.TryGetValue(messageType, listeners) Then
            listeners = New List(Of IMessageListener)
            mMessages.Add(messageType, listeners)
        End If
        listeners.Add(listener)
    End Sub

    ''' <summary>
    ''' Unregisters an IMessageListener from receiving a specific type of message
    ''' </summary>
    ''' <typeparam name="messagetype"></typeparam>
    ''' <remarks></remarks>
    Public Sub UnregisterListener(Of messagetype)(listener As IMessageListener)
        Dim listeners As List(Of IMessageListener) = Nothing
        If mMessages.TryGetValue(GetType(messagetype), listeners) Then
            listeners.Remove(listener)
            If listeners.Count = 0 Then
                mMessages.Remove(GetType(messagetype))
            End If
        End If
    End Sub
    Public Sub UnregisterListener(messagetype As Type, listener As IMessageListener)
        Dim listeners As List(Of IMessageListener) = Nothing
        If mMessages.TryGetValue(messagetype, listeners) Then
            listeners.Remove(listener)
            If listeners.Count = 0 Then
                mMessages.Remove(messagetype)
            End If
        End If
    End Sub

    Public Sub SendMessage(sender As KeyedViewModelBase, message As MessageBase)
        Dim listeners As List(Of IMessageListener) = Nothing
        If mMessages.TryGetValue(message.GetType, listeners) Then
            For i As Integer = listeners.Count - 1 To 0 Step -1
                Dim listener As IMessageListener = listeners(i)
                If listener.Key = sender.Key Then
                    listener.MessageReceived(sender, message)
                End If
            Next
        End If
    End Sub

    Public Sub BroadcastMessage(message As MessageBase)
        Dim listeners As List(Of IMessageListener) = Nothing
        If mMessages.TryGetValue(message.GetType, listeners) Then
            For i As Integer = listeners.Count - 1 To 0 Step -1
                If message.Handled Then
                    Exit For
                End If
                Dim listener As IMessageListener = listeners(i)
                listener.MessageReceived(Nothing, message)
            Next
        End If
    End Sub
End Class
